#include "parser.hpp"
#include <cctype>
#include <string>
#include <regex>
#include <iostream>
Parser::Parser(std::vector<Token> tokens) : t(std::move(tokens)) {}
std::string Parser::here(const Token &tok)
{
    return std::to_string(tok.line) + ":" + std::to_string(tok.col);
}

Token &Parser::peek()
{
    return t[i];
}
Token &Parser::get()
{
    return t[i++];
}
bool Parser::accept(TokType tp, std::string lex)
{
    if (peek().type == tp && (lex.empty() || peek().lex == lex))
    {
        get();
        return true;
    }
    return false;
}
void Parser::expect(TokType tp, std::string lex)
{
    if (!accept(tp, lex))
        throw std::runtime_error("Parse error at " + std::to_string(peek().line) + ":" + std::to_string(peek().col) + " expecting " + (lex.empty() ? "token" : lex));
}

std::unique_ptr<Stmt> Parser::parseOne()
{
    if (peek().type == TokType::KW && peek().lex == "CREATE")
    {
        if (t[i + 1].lex == "TABLE")
            return parseCreate();
        if (t[i + 1].lex == "INDEX" || t[i + 1].lex == "UNIQUE")
            return parseCreateIndex();
    }

    if (peek().type == TokType::KW && peek().lex == "INSERT")
        return parseInsert();

    if (peek().type == TokType::KW && peek().lex == "SELECT")
        return parseSelect();

    if (peek().type == TokType::KW && peek().lex == "DELETE")
        return parseDelete();

    if (peek().type == TokType::KW && peek().lex == "DROP")
        return parseDrop();

    if (peek().type == TokType::KW && peek().lex == "ALTER")
        return parseAlter();

    if (peek().type == TokType::KW && peek().lex == "SHOW")
        return parseShow();
    if (peek().type == TokType::KW && peek().lex == "UPDATE")
        return parseUpdate();
    throw std::runtime_error("Unknown statement at " + std::to_string(peek().line) + ":" + std::to_string(peek().col));
}
// CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50) NOT NULL, age INT DEFAULT 18, email VARCHAR(100) UNIQUE, active BOOLEAN DEFAULT TRUE, created_at DATETIME,comment VARCHAR(200));
std::unique_ptr<Stmt> Parser::parseCreate()
{
    expect(TokType::KW, "CREATE");
    expect(TokType::KW, "TABLE");

    std::string name = (expectIdent(), prevIdent);

    expect(TokType::DELIM, "(");
    std::vector<ColumnDef> cols;
    bool first = true;

    while (true)
    {
        if (!first)
            expect(TokType::DELIM, ","); // 消耗逗号
        first = false;

        ColumnDef c = parseColumnType((expectIdent(), prevIdent));
        std::cout << "Parsed column: " << prevIdent << std::endl;
        cols.push_back(c);

        if (accept(TokType::DELIM, ")"))
            break;
    }
    expect(TokType::DELIM, ";");
    auto p = std::make_unique<CreateTableStmt>();
    p->name = name;
    p->cols = move(cols);
    return p;
}

std::unique_ptr<Stmt> Parser::parseInsert()
{
    expect(TokType::KW, "INSERT");
    expect(TokType::KW, "INTO");
    std::string table = (expectIdent(), prevIdent);

    expect(TokType::DELIM, "(");
    std::vector<std::string> cols;
    bool first = true;
    while (true)
    {
        if (!first)
            expect(TokType::DELIM, ",");
        first = false;
        (expectIdent(), cols.push_back(prevIdent));
        if (accept(TokType::DELIM, ")"))
            break;
        if (peek().lex == ")")
        {
            get();
            break;
        }
    }
    expect(TokType::KW, "VALUES");
    expect(TokType::DELIM, "(");
    std::vector<InsertStmt::Val> vals;
    first = true;
    while (true)
    {
        if (!first)
            expect(TokType::DELIM, ",");
        first = false;
        vals.push_back(parseValue());
        if (accept(TokType::DELIM, ")"))
            break;
        if (peek().lex == ")")
        {
            get();
            break;
        }
    }
    expect(TokType::DELIM, ";");
    auto p = std::make_unique<InsertStmt>();
    p->table = table;
    p->colNames = std::move(cols);
    p->values = std::move(vals);
    return p;
}

std::unique_ptr<SelectStmt> Parser::parseSelect()
{
    expect(TokType::KW, "SELECT");
    std::vector<std::string> proj;
    if (accept(TokType::OP, "*"))
        proj.push_back("*");
    else
    {
        bool first = true;
        while (true)
        {
            if (!first)
                expect(TokType::DELIM, ",");
            first = false;
            (expectIdent(), proj.push_back(prevIdent));
            if (peek().type == TokType::KW && peek().lex == "FROM")
                break;
        }
    }
    expect(TokType::KW, "FROM");
    expectIdent();
    std::string table = prevIdent;
    auto p = std::make_unique<SelectStmt>();
    p->proj = std::move(proj);
    p->table = table;

    if (accept(TokType::KW, "WHERE"))
    {
        p->where = parseCondition();
    }
    // --- ORDER BY ---
    if (accept(TokType::KW, "ORDER"))
    {
        expect(TokType::KW, "BY");
        while (true)
        {
            OrderBy item;

            if (accept(TokType::KW, "RAND"))
            {
                // RAND()
                item.order_type = "RAND";
                expect(TokType::DELIM, "(");
                if (peek().type == TokType::INTLIT)
                {
                    item.seed = std::stoi(expectInt());
                }
                expect(TokType::DELIM, ")");
            }
            else
            {
                // 普通列
                expectIdent();
                item.order_by = prevIdent;

                if (accept(TokType::KW, "ASC"))
                {
                    item.order_type = "ASC";
                }
                else if (accept(TokType::KW, "DESC"))
                {
                    item.order_type = "DESC";
                }
            }

            p->orderBy.push_back(item);

            if (!accept(TokType::DELIM, ","))
                break;
        }
    }

    // --- LIMIT ---
    if (accept(TokType::KW, "LIMIT"))
    {
        if (peek().type != TokType::INTLIT)
            throw std::runtime_error("Expect integer after LIMIT at " + here(peek()));

        int first = std::stoi(get().lex);

        if (accept(TokType::DELIM, ","))
        {
            // MySQL: LIMIT offset,count
            if (peek().type != TokType::INTLIT)
                throw std::runtime_error("Expect integer after LIMIT offset, at " + here(peek()));
            int second = std::stoi(get().lex);
            p->offset = first;
            p->limit = second;
        }
        else if (accept(TokType::KW, "OFFSET"))
        {
            // PostgreSQL: LIMIT count OFFSET offset
            if (peek().type != TokType::INTLIT)
                throw std::runtime_error("Expect integer after OFFSET at " + here(peek()));
            int offset = std::stoi(get().lex);
            p->offset = offset;
            p->limit = first;
        }
        else
        {
            // LIMIT count
            p->limit = first;
        }
    }
    expect(TokType::DELIM, ";");
    return p;
}

std::unique_ptr<Stmt> Parser::parseDelete()
{
    expect(TokType::KW, "DELETE");
    expect(TokType::KW, "FROM");
    std::string table = (expectIdent(), prevIdent);
    auto p = std::make_unique<DeleteStmt>();
    p->table = table;
    if (accept(TokType::KW, "WHERE"))
        p->where = parseCondition();
    expect(TokType::DELIM, ";");

    return p;
}
std::unique_ptr<Stmt> Parser::parseDrop()
{
    expect(TokType::KW, "DROP");
    if (accept(TokType::KW, "TABLE"))
    {
        std::string table = (expectIdent(), prevIdent);
        expect(TokType::DELIM, ";");
        auto p = std::make_unique<DropTableStmt>();
        p->table = table;
        return p;
    }
    else if (accept(TokType::KW, "INDEX"))
    {
        std::string idx = (expectIdent(), prevIdent);
        expect(TokType::KW, "ON");
        std::string table = (expectIdent(), prevIdent);
        expect(TokType::DELIM, ";");
        auto p = std::make_unique<DropIndexStmt>();
        p->index_name = idx;
        p->table = table;
        return p;
    }
    throw std::runtime_error("Unsupported DROP statement at " + here(peek()));
}
std::unique_ptr<Stmt> Parser::parseUpdate()
{
    expect(TokType::KW, "UPDATE");
    std::string table = (expectIdent(), prevIdent);

    expect(TokType::KW, "SET");

    std::unordered_map<std::string, Value> assigns;
    do
    {
        std::string col = (expectIdent(), prevIdent);
        expect(TokType::OP, "=");

        if (peek().type == TokType::STRLIT || peek().type == TokType::INTLIT ||
            peek().type == TokType::KW)
        {
            Value val = get().lex;
            assigns.emplace(col, val);
        }
        else
        {
            throw std::runtime_error("Expect literal after = at " + here(peek()));
        }
    } while (accept(TokType::DELIM, ","));

    std::unique_ptr<Condition> cond;
    if (accept(TokType::KW, "WHERE"))
    {
        cond = parseCondition();
    }

    expect(TokType::DELIM, ";");

    auto p = std::make_unique<UpdateStmt>();
    p->table = table;
    p->assigns = std::move(assigns);
    p->where = std::move(cond);
    return p;
}

std::unique_ptr<Stmt> Parser::parseAlter()
{
    expect(TokType::KW, "ALTER");
    expect(TokType::KW, "TABLE");
    std::string table = (expectIdent(), prevIdent);

    auto p = std::make_unique<AlterTableStmt>();
    p->table = table;

    if (accept(TokType::KW, "ADD"))
    {
        expect(TokType::KW, "COLUMN");
        std::string colName = (expectIdent(), prevIdent);
        ColumnDef c = parseColumnType(colName);
        p->action = "ADD_COLUMN";
        p->colDef = c;
    }
    else if (accept(TokType::KW, "MODIFY"))
    {
        expect(TokType::KW, "COLUMN");
        std::string colName = (expectIdent(), prevIdent);
        p->action = "MODIFY_COLUMN";
        p->colDef = parseColumnType(colName);
    }
    else if (accept(TokType::KW, "CHANGE"))
    {
        expect(TokType::KW, "COLUMN");
        std::string oldName = (expectIdent(), prevIdent);
        std::string newName = (expectIdent(), prevIdent);
        p->action = "CHANGE_COLUMN";
        p->oldName = oldName;
        p->colDef = parseColumnType(newName);
    }
    else if (accept(TokType::KW, "DROP"))
    {
        expect(TokType::KW, "COLUMN");
        std::string colName = (expectIdent(), prevIdent);
        p->action = "DROP_COLUMN";
        p->oldName = colName;
    }
    else if (accept(TokType::KW, "RENAME"))
    {
        if (accept(TokType::KW, "TO"))
        {
            std::string newTable = (expectIdent(), prevIdent);
            p->action = "RENAME_TABLE";
            p->newName = newTable;
        }
        else if (accept(TokType::KW, "COLUMN"))
        {
            std::string oldName = (expectIdent(), prevIdent);
            expect(TokType::KW, "TO");
            std::string newName = (expectIdent(), prevIdent);
            p->action = "CHANGE_COLUMN";
            p->oldName = oldName;
            p->colDef.name = newName; // 只改名，不改其他属性
        }
        else
        {
            throw std::runtime_error("Expect TO or COLUMN after RENAME");
        }
    }
    else if (accept(TokType::KW, "COMMENT"))
    {
        expect(TokType::OP, "=");
        if (peek().type != TokType::STRLIT)
            throw std::runtime_error("Expect string after COMMENT =");
        p->action = "MODIFY_COMMENT";
        p->newComment = get().lex;
    }
    else
    {
        throw std::runtime_error("Unsupported ALTER TABLE action at " + here(peek()));
    }

    expect(TokType::DELIM, ";");
    return p;
}

std::unique_ptr<Stmt> Parser::parseCreateIndex()
{
    expect(TokType::KW, "CREATE");
    bool unique = accept(TokType::KW, "UNIQUE");
    expect(TokType::KW, "INDEX");
    std::string idx = (expectIdent(), prevIdent);
    expect(TokType::KW, "ON");
    std::string table = (expectIdent(), prevIdent);
    expect(TokType::DELIM, "(");
    std::vector<std::string> cols;
    bool first = true;
    while (true)
    {
        if (!first)
            expect(TokType::DELIM, ",");
        first = false;
        (expectIdent(), cols.push_back(prevIdent));
        if (accept(TokType::DELIM, ")"))
            break;
    }
    expect(TokType::DELIM, ";");
    auto p = std::make_unique<CreateIndexStmt>();
    p->index_name = idx;
    p->table = table;
    p->cols = move(cols);
    p->unique = unique;
    return p;
}
std::unique_ptr<Stmt> Parser::parseShow()
{
    expect(TokType::KW, "SHOW");
    if (accept(TokType::KW, "TABLES"))
    {
        expect(TokType::DELIM, ";");
        return std::make_unique<ShowTablesStmt>();
    }
    else if (accept(TokType::KW, "INDICES"))
    {
        expect(TokType::KW, "FROM");
        std::string table = (expectIdent(), prevIdent);
        expect(TokType::DELIM, ";");
        auto p = std::make_unique<ShowIndicesStmt>();
        p->table = table;
        return p;
    }
    throw std::runtime_error("Unsupported SHOW statement at " + here(peek()));
}

void Parser::expectIdent()
{
    if (peek().type == TokType::IDENT)
    {
        prevIdent = get().lex;
    }
    else
    {
        throw std::runtime_error("Expect identifier at " + here(peek()));
    }
}

std::string Parser::expectInt()
{
    if (peek().type == TokType::INTLIT)
    {
        std::string v = get().lex;
        return v;
    }
    throw std::runtime_error("Expect int literal at " + here(peek()));
}
InsertStmt::Val Parser::parseValue()
{
    auto t = peek();

    // 整数 / 浮点
    if (t.type == TokType::INTLIT)
    {
        int v = stoi(get().lex);
        return {InsertStmt::ValType::INT, v, 0.0, false, ""};
    }
    if (t.type == TokType::FLOATLIT)
    {
        double v = stod(get().lex);
        return {InsertStmt::ValType::DOUBLE, 0, v, false, ""};
    }

    // 字符串类
    if (t.type == TokType::STRLIT)
    {
        std::string s = get().lex;

        // 判断日期/时间格式
        if (std::regex_match(s, std::regex(R"(\d{4}-\d{2}-\d{2})")))
            return {InsertStmt::ValType::DATE, 0, 0.0, false, s};
        if (std::regex_match(s, std::regex(R"(\d{2}:\d{2}:\d{2})")))
            return {InsertStmt::ValType::TIME, 0, 0.0, false, s};
        if (std::regex_match(s, std::regex(R"(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})")))
            return {InsertStmt::ValType::DATETIME, 0, 0.0, false, s};

        // JSON 判断
        if (!s.empty() && s.front() == '{' && s.back() == '}')
            return {InsertStmt::ValType::JSON, 0, 0.0, false, s};

        // 普通字符串
        return {InsertStmt::ValType::STRING, 0, 0.0, false, s};
    }

    // 布尔
    if (t.type == TokType::KW && (t.lex == "TRUE" || t.lex == "FALSE"))
    {
        bool v = (get().lex == "TRUE");
        return {InsertStmt::ValType::BOOL, 0, 0.0, v, ""};
    }

    throw std::runtime_error("Expect value at " + here(t));
}

// 入口：解析完整 WHERE 表达式
std::unique_ptr<Condition> Parser::parseCondition()
{
    return parseOrCondition();
}

// 解析 OR 表达式
std::unique_ptr<Condition> Parser::parseOrCondition()
{
    auto left = parseAndCondition();

    while (accept(TokType::KW, "OR"))
    {
        auto node = std::make_unique<Condition>(ConditionType::OR);
        node->children.push_back(std::move(left));
        node->children.push_back(parseAndCondition());
        left = std::move(node);
    }

    return left;
}

// 解析 AND 表达式
std::unique_ptr<Condition> Parser::parseAndCondition()
{
    auto left = parsePrimaryCondition();

    while (accept(TokType::KW, "AND"))
    {
        auto node = std::make_unique<Condition>(ConditionType::AND);
        node->children.push_back(std::move(left));
        node->children.push_back(parsePrimaryCondition());
        left = std::move(node);
    }

    return left;
}

// 解析基本单元：带括号的子条件 or 简单条件
std::unique_ptr<Condition> Parser::parsePrimaryCondition()
{
    // 支持括号
    if (accept(TokType::DELIM, "("))
    {
        auto cond = parseOrCondition(); // 括号里的内容
        expect(TokType::DELIM, ")");
        return cond;
    }

    // 否则就是一个简单条件
    return parseSimpleCondition();
}

// 解析最简单的条件：col op value
std::unique_ptr<Condition> Parser::parseSimpleCondition()
{
    std::string col;
    (expectIdent(), col = prevIdent);

    std::string op;
    if (peek().type == TokType::OP &&
        (peek().lex == "=" || peek().lex == "<" || peek().lex == ">" || peek().lex == "!=" || peek().lex == "<>" ||
         peek().lex == "<=" || peek().lex == ">="))
    {
        op = get().lex;
    }
    else if (accept(TokType::KW, "LIKE")) // <<=== 新增分支
    {
        op = "LIKE";
    }
    else
    {
        throw std::runtime_error("Expect operator at " + here(peek()));
    }

    Value val;
    if (peek().type == TokType::INTLIT)
    {
        val = stoi(get().lex);
    }
    else if (peek().type == TokType::STRLIT)
    {
        val = get().lex;
    }
    else
    {
        throw std::runtime_error("Expect literal at " + here(peek()));
    }

    auto cond = std::make_unique<Condition>(ConditionType::SIMPLE);
    cond->column = col;
    cond->op = op;
    cond->value = val;
    return cond;
}

ColumnDef Parser::parseColumnType(const std::string &colName)
{
    ColumnDef c;
    c.name = colName;
    bool isUnsigned = false;

    // ==== 类型识别 ====
    if (accept(TokType::KW, "TINYINT"))
    {
        c.t = ColType::TINYINT;
        isUnsigned = accept(TokType::KW, "UNSIGNED");
    }
    else if (accept(TokType::KW, "SMALLINT"))
    {
        c.t = ColType::SMALLINT;
        isUnsigned = accept(TokType::KW, "UNSIGNED");
    }
    else if (accept(TokType::KW, "BIGINT"))
    {
        c.t = ColType::BIGINT;
        isUnsigned = accept(TokType::KW, "UNSIGNED");
    }
    else if (accept(TokType::KW, "INT") || accept(TokType::KW, "INTEGER"))
    {
        c.t = ColType::INT;
        isUnsigned = accept(TokType::KW, "UNSIGNED");
    }
    else if (accept(TokType::KW, "BOOLEAN") || accept(TokType::KW, "BOOL"))
    {
        c.t = ColType::BOOLEAN;
    }
    else if (accept(TokType::KW, "FLOAT"))
    {
        c.t = ColType::FLOAT;
    }
    else if (accept(TokType::KW, "DOUBLE"))
    {
        c.t = ColType::DOUBLE;
    }
    else if (accept(TokType::KW, "CHAR"))
    {
        expect(TokType::DELIM, "(");
        c.len = stoi(expectInt());
        expect(TokType::DELIM, ")");
        c.t = ColType::CHAR;
    }
    else if (accept(TokType::KW, "VARCHAR"))
    {
        expect(TokType::DELIM, "(");
        c.len = stoi(expectInt());
        expect(TokType::DELIM, ")");
        c.t = ColType::VARCHAR;
    }
    else if (accept(TokType::KW, "TEXT"))
    {
        c.t = ColType::TEXT;
    }
    else if (accept(TokType::KW, "BLOB"))
    {
        c.t = ColType::BLOB;
    }
    else if (accept(TokType::KW, "JSON"))
    {
        c.t = ColType::JSON;
    }
    else if (accept(TokType::KW, "DATE"))
    {
        c.t = ColType::DATE;
    }
    else if (accept(TokType::KW, "TIME"))
    {
        c.t = ColType::TIME;
    }
    else if (accept(TokType::KW, "DATETIME"))
    {
        c.t = ColType::DATETIME;
    }
    else if (accept(TokType::KW, "TIMESTAMP"))
    {
        c.t = ColType::TIMESTAMP;
    }
    else
    {
        throw std::runtime_error("Unsupported type at " + here(peek()));
    }

    c.isUnsigned = isUnsigned;

    // ==== 约束识别 ====
    while (true)
    {
        if (accept(TokType::KW, "NOT"))
        {
            expect(TokType::KW, "NULL");
            c.nullable = false;
        }
        else if (accept(TokType::KW, "NULL"))
        {
            c.nullable = true;
        }
        else if (accept(TokType::KW, "UNIQUE"))
        {
            c.nullable = false;
            c.unique = true;
        }
        else if (accept(TokType::KW, "PRIMARY"))
        {
            expect(TokType::KW, "KEY");
            c.nullable = false;
            c.unique = true;
            c.primary = true;
        }
        else if (accept(TokType::KW, "AUTO_INCREMENT"))
        {
            c.auto_increment = true;
        }
        else if (accept(TokType::KW, "DEFAULT"))
        {
            InsertStmt::Val v = parseValue(); // 直接用已有的解析函数
            c.default_value = v;
        }

        else if (accept(TokType::KW, "COMMENT"))
        {
            if (peek().type == TokType::STRLIT)
            {
                c.comment = get().lex;
            }
            else
            {
                throw std::runtime_error("Expect string after COMMENT at " + here(peek()));
            }
        }
        else
        {
            break; // 没有更多属性
        }
    }

    return c;
}
